package cn.hty.mymsg.api.action.send;

import cn.hty.mymsg.common.enums.ChannelType;
import cn.hty.mymsg.common.constant.CommonConstant;
import cn.hty.mymsg.common.domain.TaskInfo;
import cn.hty.mymsg.common.dto.model.ContentModel;
import cn.hty.mymsg.common.enums.RespStatusEnum;
import cn.hty.mymsg.common.pipeline.BusinessProcess;
import cn.hty.mymsg.common.pipeline.ProcessContext;
import cn.hty.mymsg.common.vo.BasicResultVO;
import cn.hty.mymsg.dao.MessageTemplateDao;
import cn.hty.mymsg.service.domain.MessageParam;
import cn.hty.mymsg.domain.MessageTemplate;
import cn.hty.mymsg.api.domain.SendTaskModel;
import cn.hty.mymsg.utils.ContentHolderUtil;
import cn.hty.mymsg.utils.TaskInfoUtils;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Throwables;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 拼装参数
 */
@Slf4j
@Service
public class SendAssembleAction implements BusinessProcess<SendTaskModel> {
    private static final String LINK_NAME = "url";

    @Autowired
    private MessageTemplateDao messageTemplateDao;
    /**
     * 获取 contentModel，替换模板msgContent中占位符信息
     */
    private static ContentModel getContentModelValue(MessageTemplate messageTemplate, MessageParam messageParam){
        //拿到渠道号码
        Integer sendChannel = messageTemplate.getSendChannel();
        //通过渠道号码获取对应渠道的class模型
        Class<? extends ContentModel> contentModelClass =ChannelType.getChanelModelClassByCode(sendChannel);
        //获取变量用于替换占位符(variables={title=11,url=111})
        Map<String, String> variables = messageParam.getVariables();
        //messageTemplate.getMsgContent()：从 MessageTemplate 对象中获取消息内容，通常是一个 JSON 格式的字符串。
        //JSON.parseObject(...)：使用 FastJSON 的 parseObject 方法将 JSON 字符串解析为 JSONObject 对象。
        //msgContent={"content":"1111","title":"{$title}","url":"{$url}"}
        JSONObject jsonObject = JSON.parseObject(messageTemplate.getMsgContent());
        // 通过反射 组装出 contentModel
            //获取字段名
        Field[] fields = ReflectUtil.getFields(contentModelClass);
        ContentModel contentModel = ReflectUtil.newInstance(contentModelClass);
        for (Field field : fields) {
            //获取字段值 originValue:"{$title}"
            String originValue = jsonObject.getString(field.getName());
            if (CharSequenceUtil.isNotBlank(originValue)){
                //开始进行替换
                String restValue = ContentHolderUtil.replacePlaceHolder(originValue, variables);
                //判断是否为json对象，是就转为对应字段类型，否则直接赋值
                Object resultObj = JSONUtil.isJson(restValue)?JSONUtil.toBean(restValue,field.getType()):restValue;
                ReflectUtil.setFieldValue(contentModel, field, resultObj);
            }
        }
        // 如果 url 字段存在，则在url拼接对应的埋点参数
        String url=(String)ReflectUtil.getFieldValue(contentModel,LINK_NAME);
        if (CharSequenceUtil.isNotBlank(url)){
            String resultUrl = TaskInfoUtils.generateUrl(url, messageTemplate.getId(), messageTemplate.getTemplateType());
            ReflectUtil.setFieldValue(contentModel, LINK_NAME, resultUrl);
        }
        return contentModel;
    }


    @Override
    public void process(ProcessContext<SendTaskModel> context) {
        SendTaskModel sendTaskModel = context.getProcessModel();
        Long messageTemplateId = sendTaskModel.getMessageTemplateId();

        try {
            Optional<MessageTemplate> messageTemplate = messageTemplateDao.findById(messageTemplateId);
            if (!messageTemplate.isPresent() || messageTemplate.get().getIsDeleted().equals(CommonConstant.TRUE)) {
                context.setNeedBreak(true).setResponse(BasicResultVO.fail(RespStatusEnum.TEMPLATE_NOT_FOUND));
                return;
            }
            List<TaskInfo> taskInfos = assembleTaskInfo(sendTaskModel, messageTemplate.get());
            sendTaskModel.setTaskInfo(taskInfos);
        } catch (Exception e) {
            context.setNeedBreak(true).setResponse(BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR));
            log.error("assemble task fail! templateId:{}, e:{}", messageTemplateId, Throwables.getStackTraceAsString(e));
        }

    }

    /**
     * 组装 TaskInfo 任务消息
     *
     * @param sendTaskModel
     * @param messageTemplate
     */
    private List<TaskInfo> assembleTaskInfo(SendTaskModel sendTaskModel, MessageTemplate messageTemplate) {
        List<MessageParam> messageParamList = sendTaskModel.getMessageParamList();
        List<TaskInfo> taskInfoList = new ArrayList<>();

        for (MessageParam messageParam : messageParamList) {

            TaskInfo taskInfo = TaskInfo.builder()
                    .messageId(TaskInfoUtils.generateMessageId())
                    .bizId(messageParam.getBizId())
                    .messageTemplateId(messageTemplate.getId())
                    .businessId(TaskInfoUtils.generateBusinessId(messageTemplate.getId(), messageTemplate.getTemplateType()))
                    .receiver(new HashSet<>(Arrays.asList(messageParam.getReceiver().split(String.valueOf(StrPool.C_COMMA)))))
                    .idType(messageTemplate.getIdType())
                    .sendChannel(messageTemplate.getSendChannel())
                    .templateType(messageTemplate.getTemplateType())
                    .msgType(messageTemplate.getMsgType())
                    .shieldType(messageTemplate.getShieldType())
                    .sendAccount(messageTemplate.getSendAccount())
                    .contentModel(getContentModelValue(messageTemplate, messageParam)).build();

            if (CharSequenceUtil.isBlank(taskInfo.getBizId())) {
                taskInfo.setBizId(taskInfo.getMessageId());
            }

            taskInfoList.add(taskInfo);
        }

        return taskInfoList;

    }
}
